#在Backtrader中实现移动平均线交叉（Moving Average Crossover）策略，涉及监控短期和长期移动平均线的交叉情况来生成交易信号。当短期移动平均线从下方穿过长期移动平均线时，通常视为买入信号；相反，当短期移动平均线从上方穿过长期移动平均线时，视为卖出信号。下面是一个基本的移动平均线交叉策略示例：

import backtrader as bt
from strategy.utils.BaoStockPandasData import BaoStockPandasData
from utils.DataSource import get_stock_data2

class MovingAverageCrossStrategy(bt.Strategy):
    params = (
        ('short_period', 10),  # 短期移动平均线周期
        ('long_period', 30),  # 长期移动平均线周期
        ('order_percentage', 0.95),  # 交易资金占总资金的百分比
    )

    def __init__(self):
        self.data_close = self.datas[0].close
        self.order = None
        self.short_ma = bt.indicators.SimpleMovingAverage(self.data_close, period=self.params.short_period)
        self.long_ma = bt.indicators.SimpleMovingAverage(self.data_close, period=self.params.long_period)

    def next(self):
        if self.order:
            return  # 如果有订单在执行，则不执行新的买卖操作

        # 当短期均线上穿长期均线，视为买入信号
        if self.short_ma[0] > self.long_ma[0] and not self.position:
            amount_to_invest = (self.params.order_percentage * self.broker.cash) / self.data_close[0]
            self.buy(size=amount_to_invest)
            self.log(f"BUY EXECUTED --- Price: {self.data_close[0]}")

        # 当短期均线下穿长期均线，视为卖出信号
        elif self.short_ma[0] < self.long_ma[0] and self.position:
            self.sell()
            self.log(f"SELL EXECUTED --- Price: {self.data_close[0]}")

    def log(self, txt, dt=None):
        ''' Logging function for this strategy'''
        dt = dt or self.datas[0].datetime.date(0)
        print('%s, %s' % (dt.isoformat(), txt))

    def notify_order(self, order):
        if order.status in [order.Submitted, order.Accepted]:
            return  # 订单状态未最终确定，等待

        if order.status in [order.Completed]:
            if order.isbuy():
                self.log(f"BUY EXECUTED --- Price: {order.executed.price}, Cost: {order.executed.value}, Commission: {order.executed.comm}")
            else:  # Sell
                self.log(f"SELL EXECUTED --- Price: {order.executed.price}, Size: {order.executed.size}, Commission: {order.executed.comm}")

        elif order.status in [order.Canceled, order.Margin, order.Rejected]:
            self.log('Order Canceled/Margin/Rejected')

        self.order = None

# 回测设置示例
if __name__ == '__main__':
    cerebro = bt.Cerebro()

    # 假设已经通过某种方式（如Yahoo Finance）获取了数据
    df = get_stock_data2("sh.600000", "2020-01-01", "2023-12-31")
    data = BaoStockPandasData(dataname=df)
    cerebro.adddata(data)

    cerebro.addstrategy(MovingAverageCrossStrategy, short_period=10, long_period=30)

    cerebro.broker.setcash(100000.0)
    cerebro.broker.set_coc(True)  # 现金交易模式

    print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
    cerebro.run()
    print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
    
#这个策略中，我们定义了短期（short_period）和长期（long_period）移动平均线的周期，并利用bt.indicators.SimpleMovingAverage计算这两条均线。当短期均线超过长期均线时，策略发出买入指令；当短期均线下穿长期均线时，策略执行卖出操作。用户可以根据不同市场和资产的特性调整均线的周期长度。